用acme.sh帮你免费且自动更新的HTTPS证书,省时又省力 您所在的位置:网站首页 Linux 安装证书 用acme.sh帮你免费且自动更新的HTTPS证书,省时又省力

用acme.sh帮你免费且自动更新的HTTPS证书,省时又省力

#用acme.sh帮你免费且自动更新的HTTPS证书,省时又省力| 来源: 网络整理| 查看: 265

前言

一直想更新一下https,最近刚好有点空,就实现了一下。

之前看过一篇教你快速撸一个免费HTTPS证书的文章,通过Certbot来管理Let's Encrypt的证书,使用前需要安装一堆库,觉得不太友好。所谓条条大路通罗马,肯定还有其他方法可以做这个事情。

经过一番研究oneinstack的内部,也发现了oneinstack使用 acme.sh 这个库,这个是用Shell脚本编写的,不需要安装其他东西,比较纯净,觉得比较适合自己,记录一下过程。

准备工作一个已解析好的域名(可以用http来访问)。开启服务器的443端口防火墙。步骤一、安装acme.shcurl https://get.acme.sh | sh具体参考这几篇:https://www.v2ex.com/t/656367https://www.v2ex.com/t/656394https://m.cnbeta.com/view/960295.htm一些网站https证书出现问题的情况分析(最后这篇说很多大站都受影响了)

HTTPS 加密通信挺重要的,之前也听说过 MITM(中间人攻击),不过这还是第一次听说证书被劫持的……

怎么说好呢,应该可以说网络上不能保证绝对安全吧,或者说绝对安全是不存在的。

想起来之前搭建的一个服务还没上 HTTPS,然而想不起来之前是怎么配置 SSL 证书的了,然后又得去找资料烦死了,于是这回顺便来记录一下好了啦。(摊手

通过 Let’s encrypt 可以获得 90 天免费且可续期的 SSL 证书,而利用 acme.sh 可以自动生成和更新,就来介绍一下配置的过程吧。

当然,你还可以尝试用 Let’s Encrypt 的 certbot 工具来签发证书,不过要装一堆库吧,我也不记得了……

下面的内容涉及 acme.sh 的安装,证书的签发及认证,如何安装到 nginx,以及自动更新证书、更新 acme.sh 等。

0x01 安装 acme.sh

bash

curl https://get.acme.sh | sh

或者

bash

wget -O - https://get.acme.sh | sh

执行上面的命令,它会:

从 GitHub 上下载 sh 脚本并执行把文件解压到用户的 ~/.acme.sh目录下给命令行设置一个acme.sh的 alias 别名最后注册一个 cron 定时任务来自动更新证书。

安装完成后要自行重启命令行,或者重新加载一下.bashrc文件(source ~/.bashrc)。

然后看一下有没有生效。

bash

$ acme.sh -h https://github.com/acmesh-official/acme.sh v2.8.6 Usage: acme.sh command ...[parameters].... Commands: --help, -h Show this help message. --version, -v Show version info. --install Install acme.sh to your system. --uninstall Uninstall acme.sh, and uninstall the cron job. --upgrade Upgrade acme.sh to the latest code from https://github.com/acmesh-official/acme.sh. --issue Issue a cert. --signcsr Issue a cert from an existing csr. --deploy Deploy the cert to your server. --install-cert Install the issued cert to apache/nginx or any other server. # ......2 签发 SSL 证书

签发 SSL 证书需要证明这个域名是属于你的,即域名所有权,一般有两种方式验证:http 和 dns 验证。

通过 acme.sh 可以签发单域名、多域名、泛域名证书,还可以签发 ECC 证书。为了简单起见,这里以单域名证书为例,后面再拓展一下好了。

下面任意一种方式只要安装成功了就行!

注意:这一步只是生成了证书,并没有进行配置,因此访问网站当然上不了 https。

2.1 HTTP 验证

这种方式 acme.sh 会自动在你的网站根目录下放置一个文件,来验证你的域名所有权,验证之后就签发证书,最后会自动删除验证文件。

前提是要绑定的域名已经绑定到了所在服务器上,且可以通过公网进行访问!

2.1.1 Webroot mode

假设服务器在运行着的,网站域名为 example.com,根目录为 /home/wwwroot/example.com。那么只需要执行下面这条语句就行。

bash

acme.sh --issue -d example.com -w /home/wwwroot/example.com

2.1.2 Apache / Nginx mode

如果用的是 Apache 或者 Nginx 服务器,可以自动寻找配置文件来进行签发。

bash

acme.sh --issue -d example.com --apache # Apache acme.sh --issue -d example.com --nginx # Nginx

如果找不到配置文件的话可以自行配置。

bash

acme.sh --issue -d example.com --nginx /etc/nginx/nginx.conf # 指定nginx的conf acme.sh --issue -d example.com --nginx /etc/nginx/conf.d/example.com.conf # 指定网站的conf

2.1.3 Standalone mode

这种方式下,acme.sh 会自己建立一个服务器来完成签发。主要适合的是没有建立服务器的情况,不过其实有服务器的话只要暂时关闭,不造成端口冲突就能使用。

http 模式,80端口:

bash

acme.sh --issue -d example.com --standalone

如果用了反代之类的不是 80 端口,则可以手动指定。

bash

acme.sh --issue -d example.com --standalone --httpport 88

当然它还支持 tls 模式,不是 443 端口的话也可以自行指定。

bash

acme.sh --issue -d example.com --alpn acme.sh --issue -d example.com --alpn --tlsport 8443 # 自行指定tls端口2.2 DNS 验证

这种方式下,不需要任何服务器,不需要任何公网 ip,只需要 dns 的解析记录即可完成验证。

比如说服务器不能直接公网访问,以及某些 VPS 直接绑定域名没备案的话是上不去的,就需要采用这种方案了。(我的就是了

当然,手里有域名只是想生成一个证书而已也可以这么用。

2.2.1 DNS API mode

这种方式贼强大,直接可以利用域名服务商提供的 API 就可以自动帮你添加 TXT 记录完成验证和证书签发。而且60天后还可以自动完成续期。(我就是用这种方式实现哒~

比如说 CloudFlare 的,在这里获取你的API Key。可以用全局 API Key,将参数导入到命令行。

bash

export CF_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" export CF_Account_ID="xxxxxxxxxxxxx"

为了限制权限,可以新建一个区域的 API Key. 这里只需要 Zone.DNS 的编辑权限(restrict the API Token only for write access to Zone.DNS for a single domain)就行。

bash

export CF_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" export CF_Account_ID="xxxxxxxxxxxxx" export CF_Zone_ID="xxxxxxxxxxxxx"

Account_ID 和 Zone_ID 在域名的管理页面右下方可以得到。

而后再签发证书。

bash

acme.sh --issue --dns dns_cf -d example.com

之后这些配置信息会保存到 ~/.acme.sh/account.conf 这个文件里,在证书续期或者其他利用 CF 进行验证的时候会自动调用。

当然,国内一般用的是 DNSPod,也提供了 API,类似配置就好了。

bash

export DP_Id="1234" export DP_Key="sADDsdasdgdsf" acme.sh --issue --dns dns_dp -d example.com -d www.example.com

(这个其实就是多域名签发了)

更多例子参考官方 Wiki 好了→ How to use DNS API

2.2.2 DNS manual mode

适合域名服务商没有提供 API 的情况,需要自己在域名配置一个 TXT 记录,且不能自动续期,每次都需要重新配置。

bash

acme.sh --issue -d example.com --dns -d www.example.com

更多请参考官方教程 DNS manual mode。

2.2.3 DNS alias mode

如果域名服务商没有提供 API,或者是一个挺重要的域名,为了安全不希望或者不方便直接配置这个域名的解析记录,可以通过另一个没那么重要的域名(可能是专门用来签发证书的)间接进行配置。

实际上还是需要有一个域名来验证所有权啦!

更多参考官方教程 DNS alias mode 好了。

2.3 多域名配置

多个域名签发同一张证书。只需要在验证方式之后添加多个 -d 参数就行。

bash

acme.sh --issue -d example.com -w /home/wwwroot/example.com -d www.example.com acme.sh --issue -d example.com --standalone -d www.example.com acme.sh --issue -d example.com --dns -d www.example.com

也可以多个域名指定不同的验证方式,例如

bash

acme.sh --issue \ -d aa.com -w /home/wwwroot/aa.com \ -d bb.com --dns dns_cf \ -d cc.com --apache \ -d dd.com -w /home/wwwroot/dd.com2.4 泛域名配置

Wildcard certificates

同理,只需要加个*就好。不过好像只适用于 DNS 验证的方式。

bash

acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf2.5 签发 ECC 证书

默认签发的都是基于 RSA 密钥加密的证书,而 ECC (Elliptic Curve Cryptography, 椭圆曲线密码) 密钥的保密性比 RSA 更好,密钥长度更短,更能对抗量子解密等,目前现代的操作系统和浏览器都支持 ECC 证书了(Windows XP 及其之前的就算了)。

Let's Encrypt 提供了 ECDSA 证书的签发,且 acme.sh 也支持。

我看网上的教程基本没讲 ECC 证书的签发,这里就来整一下呗!

其实只需要加上一个以 ec- 为前缀的 --keylength 参数(或 -k)就可以了。理论上上面的各种验证方式都适用。

比如

bash

acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256 # 单域名 acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com --keylength ec-256 # 多域名

支持以下长度的证书,一般就用 ec-256 就行了。

ec-256 (prime256v1, “ECDSA P-256”)ec-384 (secp384r1, “ECDSA P-384”)ec-521 (secp521r1, “ECDSA P-521”, which is not supported by Let’s Encrypt yet.)

0x03 安装(copy)证书

签发证书成功后,需要把证书安装或者复制到真正需要的地方,如 nginx / apache 的目录下。

官方说必须用下面的命令来安装证书,不能直接用 ~/.acme.sh/目录下的证书文件,因为那只能内部使用,且未来目录结构可能会更改。

我们只需要使用 --installcert 命令,指定目标位置,然后证书文件就会被 copy 到相应的位置了。

其中域名是必须的,其他参数是可选的。

有必要的话,可能需要对证书文件的所属权限进行一些设置。(我这边没有问题呢,就略了吧)

3.1 Nginx

bash

acme.sh --installcert -d example.com \ --key-file /path/to/keyfile/in/nginx/key.pem \ --fullchain-file /path/to/fullchain/nginx/cert.pem \ --reloadcmd "service nginx force-reload"

比如你可以在 nginx 的目录下新建一个 ssl 目录,然后把证书安装 / copy 过去。

bash

acme.sh --installcert -d example.com \ --key-file /etc/nginx/ssl/example.com.key \ --fullchain-file /etc/nginx/ssl/example.com.fullchain.cer \ --reloadcmd "service nginx force-reload"这里用的是 service nginx force-reload, 不是 service nginx reload, 据测试, reload 并不会重新加载证书, 所以用的 force-reload。Nginx 配置 ssl_certificate 使用 /etc/nginx/ssl/fullchain.cer ,而非 /etc/nginx/ssl/.cer ,否则 SSL Labs 的测试会报 Chain issues Incomplete 错误。3.2 Apache

bash

acme.sh --install-cert -d example.com \ --cert-file /path/to/certfile/in/apache/cert.pem \ --key-file /path/to/keyfile/in/apache/key.pem \ --fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \ --reloadcmd "service apache2 force-reload"

在命令中的 reloadcmd 参数很重要! 这个用来指定证书更新(Renew)后执行的命令,从而使续期后的证书生效。

默认 60 天就会续期一次,上面这些参数会记录下来并自动执行。非常方便

4 生成 dhparam.pem 文件(可选)

bash

openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

这一步是为了增强 SSL 的安全性。这里生成一个更强壮的 DHE 参数。

前向安全性(Forward Secrecy)的概念很简单:客户端和服务器协商一个永不重用的密钥,并在会话结束时销毁它。服务器上的 RSA 私钥用于客户端和服务器之间的 Diffie-Hellman 密钥交换签名。从 Diffie-Hellman 握手中获取的预主密钥会用于之后的编码。因为预主密钥是特定于客户端和服务器之间建立的某个连接,并且只用在一个限定的时间内,所以称作短暂模式(Ephemeral)。使用了前向安全性,如果一个攻击者取得了一个服务器的私钥,他是不能解码之前的通讯信息的。这个私钥仅用于 Diffie Hellman 握手签名,并不会泄露预主密钥。Diffie Hellman 算法会确保预主密钥绝不会离开客户端和服务器,而且不能被中间人攻击所拦截。nginx 依赖于 OpenSSL 给 Diffie-Hellman (DH)的输入参数。不幸的是,这意味着 Diffie-Hellman Ephemeral(DHE)将使用 OpenSSL 的默认设置,包括一个用于密钥交换的1024位密钥。因为我们正在使用2048位证书,DHE 客户端就会使用一个要比非 DHE 客户端更弱的密钥交换。

更多参考这里 Guide to Deploying Diffie-Hellman for TLS 吧。

5 配置 Nginx

没用过 Apache,这里只说 Nginx 好了。(其实也不怎么会用(小声bb

修改网站的 conf 配置文件,加入 SSL 的相关配置。

nginx

server { server_name example.com; listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; # ... # ssl 相关配置 ssl_certificate /etc/nginx/ssl/example.com.fullchain.cer; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_dhparam /etc/nginx/ssl/dhparam.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers '[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:ECDHE+AES128:RSA+AES128:ECDHE+AES256:RSA+AES256:ECDHE+3DES:RSA+3DES'; ssl_prefer_server_ciphers on; # ... }

ssl_dhparam /etc/nginx/ssl/dhparam.pem; 是在 0x04 步骤中生成的,可选。

ssl_ciphers用于指定加密套件,这里采用的是 CloudFlare 家的,具体也不是很清楚 emmm。可以参考一下 Mozilla 的 Wiki:Security/Server Side TLS

更多参数可以参考 nginx 的文档:Module ngx_http_ssl_module

TLSv1.3(可选)

现在很多网站都上 TLSv1.3 了,证书检测的网站对于 TLSv1、TLSv1.1 都认为不安全了,Firefox 自 74.0 版本开始也完全放弃对加密协议 TLS 1.0 和 TLS 1.1 的支持了。

对于 TLSv1.3 的配置,需要安装最新版的 openssl(OpenSSL 1.1.1 built with TLSv1.3或更高),而后重新编译 nginx,是有点麻烦这里懒得弄了,后面需要再折腾吧。

开启 HSTS(可选)

当然,为了更加安全,可以选择开启 HSTS(HTTP Strict Transport Security,HTTP严格传输安全协议),强制浏览器通过 https 进行访问。需要在 location 下的设置中加入一个 header。

nginx

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

接下来的一年(即31536000秒)中,浏览器看到 header 中包含 Strict-Transport-Security 的话就会自动切换到 https。

但是在首次访问网站时如果被劫持了,浏览器还是可能会通过 HTTP 明文传递信息。为此,Chrome 维护了一个 HSTS preload list,内置在浏览器中,对于 Chrome, Firefox, Opera, Safari, IE 11 and Edge 等主流浏览器也适用。可以在这里提交你的域名到这个列表里。(不过提交之前要考虑好,全站上 https 噢

如果 TLS 证书无效或不可信,用户不能忽略浏览器警告继续访问网站。这就是前几天访问 GitHub (Pages) 等网站被拦下来的原因了。

上面的配置完成后检查一下配置是否正确,而后重启 nginx。

bash

nginx -t systemctl restart nginx

之后就可以试一下能不能通过 https 来访问自己的网站啦!

到这里 SSL 配置就告一段落了,下面是一些 acme.sh 的维护相关的了。

6 更新证书

证书的有效期为 90 天,acme.sh 会 60 天更新(Renew)一次。

在安装 acme.sh 的时候就自动配置了一条 cron 任务了,会每天检查证书的情况。当然可以到 crontab 里看一下。

bash

# crontab -l 43 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

也可以试着用上面这条命令执行看一下相关的配置是否正确。

强制更新可以这样。

bash

acme.sh --renew -d example.com --force acme.sh --renew -d example.com --force --ecc # 如果用的是ECC证书0x07 停止更新证书

查看证书列表

bash

acme.sh --list

停止 Renew

bash

acme.sh --remove -d example.com [--ecc]

之后手动把目录下的证书移除就行。

0x08 升级 acme.sh

bash

acme.sh --upgrade # 手动升级 acme.sh --upgrade --auto-upgrade # 自动升级 acme.sh --upgrade --auto-upgrade 0 # 停止自动升级小结

除了上面这些配置之外,acme.sh 还提供了通知提醒,可以调用其他 API 来推送提醒,具体参考官方Wiki:notify。

总之感觉这个工具还是很实用的,大大降低了 SSL 配置的门槛呢。

草(一种植物),感觉我把官方的教程翻译了,然后又找了一些其他的资料整合起来了的亚子emmm。不过大部分还是自己手码的字啦!

实际上我这次配置的是 ECC 密钥的泛域名证书,用的是 DNS API 的模式。其实几个月前就折腾过 SSL 证书的配置了,然而过了就忘了,当时先是用 HTTP 模式进行验证,发现行不通才换的 DNS 模式。这次干脆一起理一遍好了,过程中发现原来 HTTP 模式验证比我想的还要强大,只是需求(主要是需要泛域名证书)对不上罢了。

怎么说好呢,绝对安全不大可能,都是想方设法尽可能相对安全一些呢。

希望这一篇不会浪费您的宝贵时间呢,有用的话欢迎给我买点好吃的/buy me a coffee(饿了喵

溜了溜了(

References & Extensive Reading

下面有的是官方文档,有的是博客之类的,由于时效性有些内容可能不适用了。注意一下就吼。

acme.sh GitHub 仓库官方中文说明How to issue a cert(官方Wiki)How to use DNS APISecurity/Server Side TLS(Nginx文档)Module ngx_http_ssl_module开始使用ECC证书部署HTTPSMySSL HTTPS 评级 B 升 A+Nginx开启TLSv1.3和HTTP/2etc.参考文章acme.sh说明生成免费且自动更新的SSL证书让你的网站免费开启Https访问


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有